﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Timers;
using Damany.Util.Extensions;
using DevExpress.Xpo;

namespace RemoteImaging.LicensePlate
{
    public class LicensePlateUploadMonitor : ILicensePlateEventGenerator
    {
        CarCountUpdater _carCountUpdater = new CarCountUpdater();

        private UnitOfWork _uow;

        public LicensePlateUploadMonitor(ILicenseplateProvider licenseplateProvider,
                                         ILicensePlateEventPublisher plateEventPublisher)
        {
            if (licenseplateProvider == null) throw new ArgumentNullException("licenseplateProvider");

            licenseplateProvider.NewLicenseplate += licenseplateProvider_NewLicenseplate;

            _licenseplateProvider = licenseplateProvider;
            _plateEventPublisher = plateEventPublisher;
            Configuration = new LicenseParsingConfig();
        }

        void licenseplateProvider_NewLicenseplate(object sender, MiscUtil.EventArgs<LicensePlate.LicensePlateSpec> e)
        {
            _uow = new UnitOfWork();
            var lpis = new LicensePlate.LicensePlateInfo(_uow);
            lpis.Image = e.Value.Image;
            lpis.LicensePlateNumber = e.Value.LicensePlateNumber;
            lpis.LicensePlateColor =  Helper.ConvertCodeToColor(e.Value.LicensePlateColor);
            lpis.CapturedFrom = e.Value.CapturedFrom;
            lpis.CaptureTime = e.Value.CaptureTime;
            lpis.WrongDirection = e.Value.isDrivingReversly;
            _uow.CommitChanges();

            _carCountUpdater.HandleCarCountByHour(new[] { lpis });
            try
            {
                _plateEventPublisher.PublishLicensePlate(lpis);
            }
            catch { }
        }

        private IEnumerable<LicensePlateInfo> ProcessLicensePlate(LicensePlateInfo value)
        {
            throw new NotImplementedException();
        }

        public void Start()
        {
        }


        private bool TryParsePath(string fullPath, out LicensePlateInfo licensePlateInfo)
        {
            licensePlateInfo = null;

            try
            {
                var fileName = System.IO.Path.GetFileNameWithoutExtension(fullPath);
                var strings = fileName.Split(new char[] { '-' }, System.StringSplitOptions.RemoveEmptyEntries);
                if (strings.Length < Configuration.LeastSectionCount) return false;

                licensePlateInfo = new LicensePlateInfo(_uow);

                licensePlateInfo.CaptureTime = new FileInfo(fullPath).CreationTime;
#if DEBUG
                licensePlateInfo.CaptureTime = DateTime.Now;
#endif
                licensePlateInfo.Image = AForge.Imaging.Image.FromFile(fullPath);

                var number = strings[Configuration.LicensePlateSectionIndex];
                licensePlateInfo.LicensePlateNumber = number;

                ParseLicensePlateRect(strings, licensePlateInfo);

                licensePlateInfo.LicensePlateColor = ParseColor(strings).GetDescription();

                return true;
            }
            catch { return false; }
        }

        private Color ParseColor(string[] strings)
        {
            Color color = Color.Empty;
            switch (strings[Configuration.PlateColorIndex])
            {
                case "0":
                    color = Color.Blue;
                    break;
                case "1":
                    color = Color.Black;
                    break;
                case "2":
                    color = Color.Yellow;
                    break;
                case "3":
                    color = Color.White;
                    break;
            }

            return color;
        }

        private void ParseLicensePlateRect(string[] strings, LicensePlateInfo licensePlateInfo)
        {
            if (Configuration.LicensePlatePositionIndex > -1)
            {
                var positionString = strings[Configuration.LicensePlatePositionIndex];
                var poisitionStrings = positionString.Split(new[] { Configuration.LicensePlateCoordinateSeparator },
                                                            StringSplitOptions.RemoveEmptyEntries);

                var position = ParseRectangle(poisitionStrings);

                licensePlateInfo.PlateX = position.X;
                licensePlateInfo.PlateY = position.Y;
                licensePlateInfo.PlateW = position.Width;
                licensePlateInfo.PlateH = position.Height;
            }
        }

        private static Rectangle ParseRectangle(string[] poisitionStrings)
        {
            var position = new System.Drawing.Point(int.Parse(poisitionStrings[0]), int.Parse(poisitionStrings[1]));
            var w = int.Parse(poisitionStrings[2]);
            var h = int.Parse(poisitionStrings[3]);

            var rectangle = new Rectangle(position.X, position.Y, w, h);

            return rectangle;
        }

        private bool IsInterestedEvent(FileSystemEventArgs e)
        {
            return e.ChangeType == WatcherChangeTypes.Created
                   && File.Exists(e.FullPath);
        }

        public int CameraId { get; set; }

        public LicenseParsingConfig Configuration { get; set; }


        private readonly ILicenseplateProvider _licenseplateProvider;
        private readonly ILicensePlateEventPublisher _plateEventPublisher;
        public string PathToMonitor
        {
            get
            {
                lock (_pathLocker)
                {
                    return _pathToMonitor;
                }
            }
            set
            {
                lock (_pathLocker)
                {
                    if (_pathToMonitor == value)
                        return;
                    _pathToMonitor = value;
                }
            }
        }



        private Timer _timer;

        private object _pathLocker = new object();
        private string _pathToMonitor;



    }
}
